﻿
using NLog;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using WxTenpay.Common;

namespace WxTenpay.Service
{
    public class BaseService<T> : DbContext, IBaseService<T> where T : class, new()
    {

        #region  异步操作
        #region 添加操作
        /// <summary>
        /// 添加一条数据
        /// </summary>
        /// <param name="parm">T</param>
        /// <returns></returns>
        public async Task<ApiResult<string>> AddAsync(T parm, bool Async = true)
        {
            var res = new ApiResult<string>() { code = 500 };
            try
            {
                var dbres = Async ? await Db.Insertable<T>(parm).ExecuteCommandAsync() : Db.Insertable<T>(parm).ExecuteCommand();
                res.data = dbres.ToString();
                res.code = 200;
            }
            catch (Exception ex)
            {
                res.info = ex.Message;
                throw;
            }
            return res;
        }

        /// <summary>
        /// 批量添加数据
        /// </summary>
        /// <param name="parm">List<T></param>
        /// <returns></returns>
        public async Task<ApiResult<string>> AddListAsync(List<T> parm, bool Async = true)
        {
            var res = new ApiResult<string>() { code = 500 };
            try
            {
                var dbres = Async ? await Db.Insertable<T>(parm).ExecuteCommandAsync() : Db.Insertable<T>(parm).ExecuteCommand();
                res.data = dbres.ToString();
                res.code = 200;
            }
            catch (Exception ex)
            {
                res.info = ex.Message;
                var log = new LogFactory().GetLogger("ErrorLog");
                log.Error(ex.ToString());
                throw;
            }
            return res;
        }
        #endregion

        #region 查询操作
        /// <summary>
        /// 获得一条数据
        /// </summary>
        /// <param name="where">Expression<Func<T, bool>></param>
        /// <returns></returns>
        public async Task<ApiResult<T>> GetModelAsync(Expression<Func<T, bool>> where, bool Async = true)
        {
            try
            {
                var res = new ApiResult<T>
                {
                    code = 200,
                    data = Async ? await Db.Queryable<T>().Where(where).FirstAsync() ?? new T() { }
               : Db.Queryable<T>().Where(where).First() ?? new T() { }
                };
                return res;
            }
            catch (Exception ex)
            {
                var log = new LogFactory().GetLogger("ErrorLog");
                log.Error(ex.ToString());

                throw;
            }

        }

        /// <summary>
        /// 获得一条数据
        /// </summary>
        /// <param name="parm">string</param>
        /// <returns></returns>
        public async Task<ApiResult<T>> GetModelAsync(string parm, bool Async = true)
        {
            try
            {
                var res = new ApiResult<T>
                {
                    code = 200,
                    data = Async ? await Db.Queryable<T>().Where(parm).FirstAsync() ?? new T() { }
               : Db.Queryable<T>().Where(parm).First() ?? new T() { }
                };
                return res;
            }
            catch (Exception ex)
            {
                var log = new LogFactory().GetLogger("ErrorLog");
                log.Error(ex.ToString());
                throw;
            }

        }

        /// <summary>
		/// 获得列表——分页
		/// </summary>
		/// <param name="parm">PageParm</param>
		/// <returns></returns>
        public async Task<ApiResult<PageModel.Page<T>>> GetPagesAsync(PageModel.PageParm parm, bool Async = true)
        {
            var res = new ApiResult<PageModel.Page<T>>();
            try
            {
                res.data = Async ? await Db.Queryable<T>()
                        .ToPageAsync(parm.page, parm.limit) : Db.Queryable<T>()
                        .ToPage(parm.page, parm.limit);
            }
            catch (Exception ex)
            {
                var log = new LogFactory().GetLogger("ErrorLog");
                log.Error(ex.ToString());
                res.info = ex.Message;
                res.code = 500;
                throw;
            }
            return res;
        }

        /// <summary>
        /// 分页
        /// </summary>
        /// <param name="parm">分页参数</param>
        /// <param name="where">条件</param>
        /// <param name="order">排序值</param>
        /// /// <param name="OrderBy">1:正序  2：倒序</param>
        /// <returns></returns>
        public async Task<ApiResult<PageModel.Page<T>>> GetPagesAsync(PageModel.PageParm parm, Expression<Func<T, bool>> where,
            Expression<Func<T, object>> order, int OrderBy = 1, bool Async = true)
        {
            var res = new ApiResult<PageModel.Page<T>>();
            try
            {
                var query = Db.Queryable<T>()
                        .Where(where)
                        .OrderByIF(OrderBy == 1, order, SqlSugar.OrderByType.Asc)
                        .OrderByIF(OrderBy == 2, order, SqlSugar.OrderByType.Desc);
                res.data = Async ? await query.ToPageAsync(parm.page, parm.limit) : query.ToPage(parm.page, parm.limit);
            }
            catch (Exception ex)
            {
                var log = new LogFactory().GetLogger("ErrorLog");
                log.Error(ex.ToString());

                res.info = ex.Message;
                res.code = 500;
                throw;
            }
            return res;
        }

        /// <summary>
		/// 获得列表
		/// </summary>
		/// <param name="parm">PageParm</param>
		/// <returns></returns>
        public async Task<ApiResult<List<T>>> GetListAsync(Expression<Func<T, bool>> where,
            Expression<Func<T, object>> order, bool Async = true)
        {
            var res = new ApiResult<List<T>>();
            try
            {
                var query = Db.Queryable<T>()
                        .Where(where).OrderBy(order);

                res.data = Async ? await query.ToListAsync() : query.ToList();
            }
            catch (Exception ex)
            {
                res.info = ex.Message;
                res.code = 500;
                throw;
            }
            return res;
        }

        /// <summary>
        /// 获得列表，不需要任何条件
        /// </summary>
        /// <returns></returns>
        public async Task<ApiResult<List<T>>> GetListAsync(bool Async = true)
        {
            var res = new ApiResult<List<T>>();
            try
            {
                res.data = Async ? await Db.Queryable<T>().ToListAsync() : Db.Queryable<T>().ToList();
            }
            catch (Exception ex)
            {
                var log = new LogFactory().GetLogger("ErrorLog");
                log.Error(ex.ToString());
                res.info = ex.Message;
                res.code = 500;
                throw;
            }
            return res;
        }
        #endregion

        #region 修改操作
        /// <summary>
        /// 修改一条数据
        /// </summary>
        /// <param name="parm">T</param>
        /// <returns></returns>
        public async Task<ApiResult<string>> UpdateAsync(T parm, bool Async = true)
        {
            var res = new ApiResult<string>() { code = 500 };
            try
            {
                var dbres = Async ? await Db.Updateable<T>(parm).ExecuteCommandAsync() : Db.Updateable<T>(parm).ExecuteCommand();
                res.data = dbres.ToString();
                res.code = 200;
            }
            catch (Exception ex)
            {
                var log = new LogFactory().GetLogger("ErrorLog");
                log.Error(ex.ToString());
                res.info = ex.Message;
                throw;
            }
            return res;
        }

        /// <summary>
        /// 批量修改
        /// </summary>
        /// <param name="parm">T</param>
        /// <returns></returns>
        public async Task<ApiResult<string>> UpdateAsync(List<T> parm, bool Async = true)
        {
            var res = new ApiResult<string>() { code = 500 };
            try
            {
                var dbres = Async ? await Db.Updateable<T>(parm).ExecuteCommandAsync() : Db.Updateable<T>(parm).ExecuteCommand();
                res.data = dbres.ToString();
                res.code = 200;
            }
            catch (Exception ex)
            {
                var log = new LogFactory().GetLogger("ErrorLog");
                log.Error(ex.ToString());
                res.info = ex.Message;
                throw;
            }
            return res;
        }

        /// <summary>
        /// 修改一条数据，可用作假删除
        /// </summary>
        /// <param name="columns">修改的列=Expression<Func<T,T>></param>
        /// <param name="where">Expression<Func<T,bool>></param>
        /// <returns></returns>
        public async Task<ApiResult<string>> UpdateAsync(Expression<Func<T, T>> columns,
            Expression<Func<T, bool>> where, bool Async = true)
        {
            var res = new ApiResult<string>() { code = 500 };
            try
            {
                var dbres = Async ? await Db.Updateable<T>().SetColumns(columns).Where(where).ExecuteCommandAsync()
                    : Db.Updateable<T>().SetColumns(columns).Where(where).ExecuteCommand();
                res.data = dbres.ToString();
                res.code = 200;
            }
            catch (Exception ex)
            {
                var log = new LogFactory().GetLogger("ErrorLog");
                log.Error(ex.ToString());
                res.info = ex.Message;
                throw;
            }
            return res;
        }
        #endregion

        #region 删除操作
        /// <summary>
        /// 删除一条或多条数据
        /// </summary>
        /// <param name="parm">string</param>
        /// <returns></returns>
        public async Task<ApiResult<string>> DeleteAsync(string parm, bool Async = true)
        {
            var res = new ApiResult<string>() { code = 500 };
            try
            {
                var list = parm.Split(',');
                var dbres = Async ? await Db.Deleteable<T>().In(list.ToArray()).ExecuteCommandAsync() : Db.Deleteable<T>().In(list.ToArray()).ExecuteCommand();
                res.data = dbres.ToString();
                res.code = 200;
            }
            catch (Exception ex)
            {
                var log = new LogFactory().GetLogger("ErrorLog");
                log.Error(ex.ToString());
                res.info = ex.Message;
                throw;
            }
            return res;
        }

        /// <summary>
        /// 删除一条或多条数据
        /// </summary>
        /// <param name="where">Expression<Func<T, bool>></param>
        /// <returns></returns>
        public async Task<ApiResult<string>> DeleteAsync(Expression<Func<T, bool>> where, bool Async = true)
        {
            var res = new ApiResult<string>() { code = 500 };
            try
            {
                var dbres = Async ? await Db.Deleteable<T>().Where(where).ExecuteCommandAsync() : Db.Deleteable<T>().Where(where).ExecuteCommand();
                res.data = dbres.ToString();
                res.code = 200;
            }
            catch (Exception ex)
            {
                var log = new LogFactory().GetLogger("ErrorLog");
                log.Error(ex.ToString());
                res.info = ex.Message;
                throw;
            }
            return res;
        }
        #endregion

        #region 查询Count
        public async Task<ApiResult<int>> CountAsync(Expression<Func<T, bool>> where, bool Async = true)
        {
            var res = new ApiResult<int>() { code = 500 };
            try
            {
                res.data = Async ? await Db.Queryable<T>().CountAsync(where) : Db.Queryable<T>().Count(where);
                res.code = 200;
            }
            catch (Exception ex)
            {
                var log = new LogFactory().GetLogger("ErrorLog");
                log.Error(ex.ToString());
                res.info = ex.Message;
                throw;
            }
            return res;
        }
        #endregion

        #region 是否存在
        public async Task<ApiResult<bool>> IsExistAsync(Expression<Func<T, bool>> where, bool Async = true)
        {
            var res = new ApiResult<bool>() { code = 500 };
            try
            {
                res.data = Async ? await Db.Queryable<T>().AnyAsync(where) : Db.Queryable<T>().Any(where);
                res.code = 200;
            }
            catch (Exception ex)
            {
                var log = new LogFactory().GetLogger("ErrorLog");
                log.Error(ex.ToString());
                res.info = ex.Message;
                throw;
            }
            return res;
        }
        #endregion

        #endregion


        #region 同步操作


        #region 添加操作
        /// <summary>
        /// 添加一条数据
        /// </summary>
        /// <param name="parm">T</param>
        /// <returns></returns>
        public int Add(T parm)
        {

            try
            {
                return Db.Insertable<T>(parm).ExecuteCommand();
            }
            catch (Exception ex)
            {
                throw;
            }

        }

        /// <summary>
        /// 批量添加数据
        /// </summary>
        /// <param name="parm">List<T></param>
        /// <returns></returns>
        public int AddList(List<T> parm)
        {
            try
            {
                return Db.Insertable<T>(parm).ExecuteCommand();
            }
            catch (Exception ex)
            {
                var log = new LogFactory().GetLogger("ErrorLog");
                log.Error(ex.ToString());
                throw;
            }

        }
        #endregion

        #region 查询操作
        /// <summary>
        /// 获得一条数据
        /// </summary>
        /// <param name="where">Expression<Func<T, bool>></param>
        /// <returns></returns>
        public T GetModel(Expression<Func<T, bool>> where)
        {
            try
            {
                return Db.Queryable<T>().Where(where).First() ?? null;
                // return Db.Queryable<T>().Where(where).First() ?? new T() { };
            }
            catch (Exception ex)
            {
                var log = new LogFactory().GetLogger("ErrorLog");
                log.Error(ex.ToString());
                throw;
            }

        }

        /// <summary>
        /// 获得一条数据
        /// </summary>
        /// <param name="parm">string</param>
        /// <returns></returns>
        public T GetModel(string parm)
        {
            try
            {
                return Db.Queryable<T>().Where(parm).First() ?? null;
                // return Db.Queryable<T>().Where(parm).First() ?? new T() { };
            }
            catch (Exception ex)
            {
                var log = new LogFactory().GetLogger("ErrorLog");
                log.Error(ex.ToString());
                throw;
            }

        }

        /// <summary>
		/// 获得列表——分页
		/// </summary>
		/// <param name="parm">PageParm</param>
		/// <returns></returns>
        public PageModel.Page<T> GetPages(PageModel.PageParm parm)
        {

            try
            {
                return Db.Queryable<T>().ToPage(parm.page, parm.limit);
            }
            catch (Exception ex)
            {
                var log = new LogFactory().GetLogger("ErrorLog");
                log.Error(ex.ToString());
                throw;
            }

        }


        /// <summary>
        /// 分页
        /// </summary>
        /// <param name="parm">分页参数</param>
        /// <param name="order">排序值</param>
        /// /// <param name="OrderBy">1:正序  2：倒序</param>
        /// <returns></returns>
        public PageModel.Page<T> GetPages(PageModel.PageParm parm,
            Expression<Func<T, object>> order, int OrderBy = 1)
        {
            try
            {
                var query = Db.Queryable<T>()
                        .OrderByIF(OrderBy == 1, order, SqlSugar.OrderByType.Asc)
                        .OrderByIF(OrderBy == 2, order, SqlSugar.OrderByType.Desc);
                return query.ToPage(parm.page, parm.limit);
            }
            catch (Exception ex)
            {
                var log = new LogFactory().GetLogger("ErrorLog");
                log.Error(ex.ToString());
                throw;
            }

        }

        /// <summary>
        /// 分页
        /// </summary>
        /// <param name="parm">分页参数</param>
        /// <param name="where">条件</param>
        /// <param name="order">排序值</param>
        /// /// <param name="OrderBy">1:正序  2：倒序</param>
        /// <returns></returns>
        public PageModel.Page<T> GetPages(PageModel.PageParm parm, Expression<Func<T, bool>> where,
            Expression<Func<T, object>> order, int OrderBy = 1)
        {
            try
            {
                var query = Db.Queryable<T>()
                        .Where(where)
                        .OrderByIF(OrderBy == 1, order, SqlSugar.OrderByType.Asc)
                        .OrderByIF(OrderBy == 2, order, SqlSugar.OrderByType.Desc);
                return query.ToPage(parm.page, parm.limit);
            }
            catch (Exception ex)
            {
                var log = new LogFactory().GetLogger("ErrorLog");
                log.Error(ex.ToString());
                throw;
            }

        }

        /// <summary>
        /// 获得列表
        /// </summary>
        /// <param name="parm">PageParm</param>
        /// <returns></returns>
        public List<T> GetList(Expression<Func<T, bool>> where)
        {
            try
            {
                var query = Db.Queryable<T>()
                        .Where(where);

                return query.ToList();
            }
            catch (Exception ex)
            {
                throw;
            }
        }

        /// <summary>
		/// 获得列表
		/// </summary>
		/// <param name="parm">PageParm</param>
		/// <returns></returns>
        public List<T> GetList(Expression<Func<T, bool>> where,
            Expression<Func<T, object>> order)
        {
            try
            {
                var query = Db.Queryable<T>()
                        .Where(where).OrderBy(order);

                return query.ToList();
            }
            catch (Exception ex)
            {
                throw;
            }
        }

        /// <summary>
        /// 获得列表，不需要任何条件
        /// </summary>
        /// <returns></returns>
        public List<T> GetList()
        {
            try
            {
                return Db.Queryable<T>().ToList();
            }
            catch (Exception ex)
            {
                var log = new LogFactory().GetLogger("ErrorLog");
                log.Error(ex.ToString());
                throw;
            }
        }
        #endregion

        #region 修改操作
        /// <summary>
        /// 修改一条数据
        /// </summary>
        /// <param name="parm">T</param>
        /// <returns></returns>
        public int Update(T parm)
        {
            try
            {
                return Db.Updateable<T>(parm).ExecuteCommand();
            }
            catch (Exception ex)
            {
                var log = new LogFactory().GetLogger("ErrorLog");
                log.Error(ex.ToString());
                throw;
            }
        }

        /// <summary>
        /// 批量修改
        /// </summary>
        /// <param name="parm">T</param>
        /// <returns></returns>
        public int Update(List<T> parm)
        {
            try
            {
                return Db.Updateable<T>(parm).ExecuteCommand();
            }
            catch (Exception ex)
            {
                var log = new LogFactory().GetLogger("ErrorLog");
                log.Error(ex.ToString());
                throw;
            }

        }

        /// <summary>
        /// 修改一条数据，可用作假删除
        /// </summary>
        /// <param name="columns">修改的列=Expression<Func<T,T>></param>
        /// <param name="where">Expression<Func<T,bool>></param>
        /// <returns></returns>
        public int Update(Expression<Func<T, T>> columns,
            Expression<Func<T, bool>> where)
        {
            try
            {
                return Db.Updateable<T>().SetColumns(columns).Where(where).ExecuteCommand();
            }
            catch (Exception ex)
            {
                var log = new LogFactory().GetLogger("ErrorLog");
                log.Error(ex.ToString());
                throw;
            }
        }
        #endregion

        #region 删除操作
        /// <summary>
        /// 删除一条或多条数据
        /// </summary>
        /// <param name="parm">string</param>
        /// <returns></returns>
        public int Delete(string parm)
        {
            try
            {
                var list = parm.Split(',');
                return Db.Deleteable<T>().In(list.ToArray()).ExecuteCommand();

            }
            catch (Exception ex)
            {
                var log = new LogFactory().GetLogger("ErrorLog");
                log.Error(ex.ToString());
                throw;
            }
        }

        /// <summary>
        /// 删除一条或多条数据
        /// </summary>
        /// <param name="where">Expression<Func<T, bool>></param>
        /// <returns></returns>
        public int Delete(Expression<Func<T, bool>> where)
        {
            try
            {
                return Db.Deleteable<T>().Where(where).ExecuteCommand();
            }
            catch (Exception ex)
            {
                var log = new LogFactory().GetLogger("ErrorLog");
                log.Error(ex.ToString());
                throw;
            }
        }
        #endregion

        #region 查询Count
        public int Count(Expression<Func<T, bool>> where)
        {
            try
            {
                return Db.Queryable<T>().Count(where);
            }
            catch (Exception ex)
            {
                var log = new LogFactory().GetLogger("ErrorLog");
                log.Error(ex.ToString());

                throw;
            }
        }
        #endregion

        #region 是否存在
        public bool IsExist(Expression<Func<T, bool>> where)
        {
            var res = new ApiResult<bool>() { code = 500 };
            try
            {
                return Db.Queryable<T>().Any(where);
            }
            catch (Exception ex)
            {
                var log = new LogFactory().GetLogger("ErrorLog");
                log.Error(ex.ToString());
                throw;
            }
       
        }
        #endregion

        #endregion

        #region 执行sql
        /// <summary>
        /// 新增 或者修改
        /// </summary>
        /// <param name="sql"></param>
        /// <param name="pams"></param>
        /// <returns></returns>
        public int insertsql(string sql, object pams)
        {
            try
            {
                return Db.Ado.ExecuteCommand(sql, pams);
            }
            catch (Exception ex)
            {
                var log = new LogFactory().GetLogger("ErrorLog");
                log.Error(ex.ToString());
                throw;
            }
        }

        /// <summary>
        /// 执行查询sql 
        /// </summary>
        /// <param name="sql"></param>
        /// <param name="pams"></param>
        /// <returns></returns>
        public List<T> SelectSql(string sql, object pams)
        {
            try
            {

                var list = Db.Ado.GetDataTable(sql, pams);
                return IListDataSet.Tolist<T>(list);
            }
            catch (Exception ex)
            {
                var log = new LogFactory().GetLogger("ErrorLog");
                log.Error(ex.ToString());
                throw;
            }
        }


        /// <summary>
        /// 执行查询sql to datatable
        /// </summary>
        /// <param name="sql"></param>
        /// <param name="pams"></param>
        /// <returns></returns>
        public DataTable DataSql(string sql, object pams)
        {
            try
            {
                return Db.Ado.GetDataTable(sql, pams);
            }
            catch (Exception ex)
            {
                var log = new LogFactory().GetLogger("ErrorLog");
                log.Error(ex.ToString());
                throw;
            }
        }
        #endregion 

    }
}
